#ifndef UTIL_ANY_H
#define UTIL_ANY_H

#include <typeinfo>
#include <cassert>
#include <algorithm> // 用于std::swap
#include "logger.h"

namespace util { // 属于通用工具，放入util命名空间

/**
 * @brief 通用类型容器，可存储任意类型的数据
 * 实现思路：通过类型擦除（type erasure）技术，将具体类型封装在内部模板类中，对外提供统一接口
 */
class Any 
{
private:
    /**
     * @brief 抽象基类，定义数据存储的接口
     * 用于擦除具体类型的信息，提供类型查询和克隆功能
     */
    class Holder 
    {
    public:
        virtual ~Holder() = default; // 虚析构，确保子类正确析构
        virtual const std::type_info& type() const = 0; // 返回存储数据的类型信息
        virtual Holder* clone() const = 0; // 克隆自身，用于复制操作
    };

    /**
     * @brief 模板子类，存储具体类型的数据
     * @tparam T 存储的数据类型
     */
    template <class T>
    class Placeholder : public Holder 
    {
    public:
        /**
         * @brief 构造函数，存储具体类型的值
         * @param val 要存储的值（通过拷贝构造）
         */
        explicit Placeholder(const T& val) : _val(val) {}

        /**
         * @brief 返回存储数据的类型信息
         * @return 类型信息（typeid(T)）
         */
        const std::type_info& type() const override 
        { return typeid(T); }

        /**
         * @brief 克隆当前对象
         * @return 新的Placeholder对象，包含相同的值
         */
        Holder* clone() const override 
        { return new Placeholder(_val); }

    public:
        T _val; // 存储的具体类型数据
    };

    Holder* _content; // 指向存储具体数据的Holder子类对象

public:
    /**
     * @brief 默认构造函数，创建空的Any对象
     */
    Any() : _content(nullptr) {}

    /**
     * @brief 模板构造函数，存储任意类型的值
     * @tparam T 存储的数据类型
     * @param val 要存储的值
     */
    template <class T>
    Any(const T& val) : _content(new Placeholder<T>(val)) {}

    /**
     * @brief 拷贝构造函数，深拷贝其他Any对象的数据
     * @param other 被拷贝的Any对象
     */
    Any(const Any& other) : _content(other._content ? other._content->clone() : nullptr) {}

    /**
     * @brief 析构函数，释放存储的数据
     */
    ~Any();

    /**
     * @brief 交换两个Any对象的数据
     * @param other 另一个Any对象
     * @return 交换后的当前对象
     */
    Any& swap(Any& other);

    /**
     * @brief 获取存储的数据的指针（类型安全检查）
     * @tparam T 期望的数据类型
     * @return 指向数据的指针，若类型不匹配则触发断言
     */
    template <class T>
    T* get()
    {
        // 检查请求的类型与存储的类型是否一致，不一致则触发断言
        assert(_content && typeid(T) == _content->type() && "Type mismatch in Any::get()");
        // 转换为具体的Placeholder<T>，返回数据指针
        return &static_cast<Placeholder<T>*>(_content)->_val;
    }

    /**
     * @brief 模板赋值运算符，存储新的任意类型值
     * @tparam T 新数据的类型
     * @param val 新值
     * @return 当前对象的引用
     */
    template <class T>
    Any& operator=(const T& val)
    {
        // 1. 创建临时Any对象，存储新值（通过模板构造函数）
        // 2. 交换临时对象与当前对象的数据（临时对象会自动释放旧数据）
        Any(val).swap(*this);
        return *this;
    }

    /**
     * @brief 赋值运算符，拷贝另一个Any对象的数据
     * @param other 另一个Any对象
     * @return 当前对象的引用
     */
    Any& operator=(const Any& other);
};

} // namespace util

#endif // UTIL_ANY_H